package cn.liwq.study.demo.netty.lab.mahjong.server;

import cn.liwq.study.demo.netty.lab.mahjong.common.codec.MahjongFrameDecoder;
import cn.liwq.study.demo.netty.lab.mahjong.common.codec.MahjongFrameEncoder;
import cn.liwq.study.demo.netty.lab.mahjong.common.codec.MahjongProtocolDecoder;
import cn.liwq.study.demo.netty.lab.mahjong.common.codec.MahjongProtocolEncoder;
import cn.liwq.study.demo.netty.lab.mahjong.server.handler.MahjongServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import org.apache.log4j.BasicConfigurator;

/**
 * @author lweiqiang
 * @date 2021/5/8
 */
public class MahjongServer {
    public static void main(String[] args) throws InterruptedException {
        BasicConfigurator.configure();
        // 1.线程池
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        // 2.引导器
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        try {
            // 3.指定线程池
            serverBootstrap
                    .group(bossGroup, workerGroup)
                    // 4.指定服务端渠道类型
                    .channel(NioServerSocketChannel.class)
                    // 5.设置参数
                    .option(ChannelOption.SO_BACKLOG, 100)
                    // 6.设置ServerSocketChannel对应的Handler，只能设置一个
                    .handler(new LoggingHandler(LogLevel.DEBUG))
                    // 7. 设置SocketChannel对应的Handler
                    .childHandler(
                            new ChannelInitializer<SocketChannel>() {
                                @Override
                                protected void initChannel(SocketChannel ch) throws Exception {
                                    ChannelPipeline pipeline = ch.pipeline();
                                    pipeline.addLast(new LoggingHandler(LogLevel.DEBUG));
                                    // 一次编解码
                                    pipeline.addLast(new MahjongFrameDecoder());
                                    pipeline.addLast(new MahjongFrameEncoder());
                                    // 二次编解码
                                    pipeline.addLast(new MahjongProtocolDecoder());
                                    pipeline.addLast(new MahjongProtocolEncoder());
                                    // 处理消息
                                    pipeline.addLast(new MahjongServerHandler());
                                }
                            });
            // 8. 绑定端口
            ChannelFuture f = serverBootstrap.bind("127.0.0.1", 8017).sync();
            // 9. 等待服务端监听端口关闭，这里会阻塞主线程
            f.channel().closeFuture().sync();
        } finally {
            // 优雅关闭
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
